/* $Id
 */
#include "encdb.h"
#include "extern.h"
#include "crypt.h"
#include "file.h"

/* OpenSSL 0.9.8 AES and MD5 */

/* pass must terminate in \0 */

unsigned char * hash_password (unsigned char *pass)
{
	unsigned char *hkey[MD5_DIGEST_LENGTH];

	return MD5(pass,strlen(pass),NULL);
}

void * encrypt_from_file (const unsigned char *pass, FILE *fd )
{
	unsigned char *outbuf = NULL;
	void *inbuf = NULL;

	int outlen = 0;
	int blklen = 0;
	int frdcnt = 0;
	off_t fsize;
	struct stat fst;

	EVP_CIPHER_CTX ctx;
	EVP_CIPHER_CTX_init(&ctx);

	/* init */
	EVP_EncryptInit(&ctx,EVP_aes_256_cfb(),NULL,NULL);
	EVP_CIPHER_CTX_set_key_length(&ctx,32); /* since is the hash of the passpharase */
	EVP_CIPHER_CTX_key_length(&ctx);
	EVP_EncryptInit(&ctx,NULL,pass,NULL);
	memset((char *)pass,0,strlen(pass));
	EVP_CIPHER_CTX_set_padding(&ctx,1);

	blklen = EVP_CIPHER_CTX_block_size(&ctx);

	/* file size */
	if ((fstat(fileno(fd), &fst)) != 0) {
	   fprintf(stderr, "%s\n", strerror(errno));
     exit(1);
	}
	fsize = fst.st_size;

	outbuf = malloc(fsize+blklen);
	inbuf = malloc(blklen);
	memset(outbuf,0,fsize+blklen);
	memset(inbuf,0,blklen);

	void *outbufptr = outbuf;

	while (1) {
		frdcnt = fread(inbuf, 1, blklen, fd);
		if ( frdcnt < blklen) break;
		EVP_EncryptUpdate(&ctx, outbuf, &outlen, inbuf, frdcnt);
		memset(inbuf,0,blklen);
		outbuf += outlen;
	}

	if (!EVP_EncryptFinal(&ctx, outbuf, &outlen ) ) {
		fprintf(stderr,"error",0);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return NULL;
	}

	EVP_CIPHER_CTX_cleanup(&ctx);

	free(inbuf);
	return outbufptr;
}

void decrypt_to_file(const unsigned char *pass, void *cryptedstr, int size, FILE *fd)
{
	unsigned char *outbuf = NULL;
	unsigned char *crypted = NULL;
	int blklen = 0;
	int blkcnt = 0;
	int outlen = 0;
	int mod = 0;
	struct stat fst;

	EVP_CIPHER_CTX ctx;
	EVP_CIPHER_CTX_init(&ctx);

	/* init */
	EVP_DecryptInit(&ctx,EVP_aes_256_cfb(),NULL,NULL);
	EVP_CIPHER_CTX_set_key_length(&ctx,32);
	EVP_DecryptInit(&ctx,NULL,pass,NULL);
	memset((char *)pass,0,strlen(pass));
	EVP_CIPHER_CTX_set_padding(&ctx,1);

	blklen = EVP_CIPHER_CTX_block_size(&ctx);

	outbuf = malloc(size);
	memset(outbuf,0,size);

	blkcnt = size / blklen;
	mod = size % blklen;

	void *outbufptr = outbuf;
	while (blkcnt--) {
		EVP_DecryptUpdate(&ctx,outbuf,&outlen,(unsigned char *)cryptedstr,blklen);
		fwrite(outbuf,1,outlen,fd);

		outbuf += outlen;
		cryptedstr += blklen;
	}

	EVP_DecryptFinal(&ctx,outbuf+outlen,&outlen);
	fwrite(outbuf,1,outlen,fd);

	EVP_CIPHER_CTX_cleanup(&ctx);

	free(outbufptr);
	return;
}

/*
 * vim:ts=2
 */
